package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.Activity;
import com.wzcl.app.dao.model.Topic;
import com.wzcl.app.dao.model.TopicInfo;
import com.wzcl.app.dao.repository.TopicInfoRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.dto.TopicInfoDto;
import com.wzcl.app.service.TopicInfoService;
import com.wzcl.app.service.TopicService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Log4j2
@Service
@Transactional
public class TopicInfoServiceImpl implements TopicInfoService {

    @Autowired
    private TopicInfoRepository repository;

    @Autowired
    private TopicService topicService;

    @Override
    public TopicInfo addTopicInfo(TopicInfoDto topicInfoDto) {
        //校验获取
        Topic topic = topicService.getAndCheckById(topicInfoDto.getTopicId());
        //创建
        TopicInfo topicInfo = new TopicInfo();
        BeanUtils.copyProperties(topicInfoDto, topicInfo, "id");
        topicInfo.setTopic(topic);
        topicInfo = repository.save(topicInfo);
        topicService.refreshScore(topic);
        return topicInfo;
    }

    @Override
    public TopicInfo delTopicInfoById(Integer id) {
        //校验获取
        TopicInfo topicInfo = getAndCheckById(id);
        //删除
        log.info("Topic:{} Physical deletion", JSON.toJSONString(topicInfo));
        repository.delete(topicInfo);
        topicService.refreshScore(topicInfo.getTopic());
        return topicInfo;
    }

    @Override
    public TopicInfo updateTopicInfo(TopicInfoDto topicInfoDto) {
        //校验获取
        TopicInfo topicInfo = getAndCheckById(topicInfoDto);
        //修改
        BeanUtils.copyProperties(topicInfoDto, topicInfo, "id", "type");
        TopicInfo save = repository.save(topicInfo);
        //若分数发生变化，则更改总分数
        topicService.refreshScore(topicInfo.getTopic());
        return save;
    }

    @Override
    public TopicInfo getTopicInfoById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public TopicInfo getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少题目Id");
        }
        TopicInfo topicInfo = getTopicInfoById(id);
        if (topicInfo == null) {
            throw new BusinessException(CodeMsg.TOPIC_INFO_NOT_EXIST);
        }
        return topicInfo;
    }

    @Override
    public List<TopicInfo> getTopicInfoList(TopicInfoDto topicInfoDto) {
        return repository.findAll(getSpecification(topicInfoDto), topicInfoDto.getSort());
    }

    @Override
    public MyPage<TopicInfo> getTopicInfoPage(TopicInfoDto topicInfoDto) {
        Page<TopicInfo> all = repository.findAll(getSpecification(topicInfoDto), topicInfoDto.getPageable());
        ArrayList<TopicInfo> list = new ArrayList<>(all.getContent());
        Collections.reverse(list);
        MyPage<TopicInfo> myPage = new MyPage<>();
        myPage.setContent(list);
        myPage.setTotalElements(all.getTotalElements());
        return myPage;
    }

    private Specification<TopicInfo> getSpecification(TopicInfoDto topicInfoDto) {
        return new Specification<TopicInfo>() {
            @Override
            public Predicate toPredicate(Root<TopicInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (topicInfoDto.getTopicId() != null) {
                    Join<TopicInfo, Topic> topicPath = root.join("topic");
                    predicates.add(criteriaBuilder.equal(topicPath.get("id"), topicInfoDto.getTopicId()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
